<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of 4DTable
 *
 * @author bonfiglio
 */
class Table4D {

    static $correspondance = array(
        0 => 'TEXT', //alpha
        1 => 'DOUBLE', //numérique(float)
        2 => 'LONGTEXT', //texte
        3 => false, //image
        4 => 'DATE', //date
        5 => false, //variable indéfinie
        6 => false, //sous table
        7 => 'BINARY(1)', //booléen
        8 => 'SMALLINT', //entier
        9 => 'INT', //entier long
        11 => 'TIME', //heure
        13 => false, //tableau 2D
        14 => false, //tableau numérique
        15 => false, //tableau entier
        16 => false, //tableau entierlong
        17 => false, //tableau date
        18 => false, //tableau texte
        19 => false, //tableau image
        20 => false, //tableau pointeur
        21 => false, //tableau chaîne
        22 => false, //tableau booléen
        23 => false, //pointeur
        24 => false, //variable chaîne
        25 => false, //entier 64 bits
        30 => false, //'BLOB', //BLOB
        35 => 'FLOAT'//Float
    );
    private $deprecatedType = array(6);
    private $Database;
    private $serverName = '4d';
    private $Structure;
    private $primaryKey = false;
    private $fields;
    private $table;
    public $requests = array();
    public $error = false;
    private $limitPerRequest = 25;
    public $log = '';

    public function __construct($table) {
        //check au préalable si la table exite
        //si la table existe
        if (true == true) {

            $this->table = $table;
            $this->Database = Database::factory($this->serverName);
            $this->urls = array(
                'struture' => 'http://192.168.25.224:8060/cny_rest_api/' . $table . '/fields/',
                'data' => 'http://192.168.25.224:8060/cny_rest_api/' . $table . '/?'
            );
        } else {
            $this->error = 'Table ' . $table . ' inconnue';
        }
    }

    public function setStructure() {
        $Webservice = new Webservice($this->urls['struture']);
        $this->Structure = $Webservice->getJSON();
        //on libere de la ressource
        unset($Webservice);
    }

    public function createTable() {
        $fieldKey = '';
        $multiKey = '';
        $sqlFields = array();

        if (!$this->error && is_object($this->Structure)) {
            foreach ($this->Structure->fields as $Field) {
                if (isset($this->correspondance[$Field->fieldType]) && $this->correspondance[$Field->fieldType] !== false) {
                    if (substr(strtolower($Field->fieldName), -3) == 'ide' && $Field->fieldType == 9) {

                        if (strlen($fieldKey)) {
                            if (!strlen($multiKey)) {
                                $multiKey.= ',
                                    KEY `index' . $this->primaryKey . '` (`' . $this->primaryKey . '` ASC)';
                            }
                            $multiKey.= ',
                                    KEY `index' . $Field->fieldName . '` (`' . $Field->fieldName . '` ASC)';
                        } else {
                            $this->primaryKey = $Field->fieldName;
                            $fieldKey = ',
                            PRIMARY KEY (`' . $Field->fieldName . '`)';
                        }
                    }
                    $this->fields[] = $Field->fieldName;
                    $sqlFields[] = '
            `' . $Field->fieldName . '` ' . $this->correspondance[$Field->fieldType];
                } else if (!in_array($Field->fieldType, $this->deprecatedType)) {
                    $this->error = 'Type de champ inconnu : ' . $Field->fieldName . '(' . $Field->fieldType . ')';
                    return false;
                }
            }
            if (!$this->primaryKey) {
                $this->error = "Pas de clé primaire !! C'est maaaaaaaaaaaaaaal !".HtmlTag::pre(print_r($this->Structure,true));
                return false;
            }
            $fieldKey = strlen($multiKey) ? $multiKey : $fieldKey;
            $sql = 'CREATE TABLE `' . $this->table . '` (' . implode(', ', $sqlFields) . $fieldKey . '
            ) 
            ENGINE=MyISAM DEFAULT CHARSET=utf8';
            try {
                $this->requests[] = $sql;
                $this->Database->DropTable($this->table);
                $this->Database->Exec($sql);
            } catch (Exception $e) {
                $this->error = 'createTable() : ' . $e->getMessage() . '.<br/>Request : ' . HtmlTag::pre($sql);
            }
        }
        //on libere de la ressource
        unset($fieldKey);
        unset($sqlFields);
    }

    public function getTimelimit() {
        $reference = 50;
        $timelimit = 240; //référence pour 50 lignes
        if (!$this->error && is_object($this->Structure)) {
            $u = $this->urls['data'] . http_build_query(array($this->primaryKey . '>' => 0, 'cny_max' => $this->limitPerRequest, 'cny_page' => 1, 'cny_sort' => $this->primaryKey));
            $Webservice = new Webservice($u);
            $Datas = $Webservice->getJSON();
            if ($Datas->pages > $reference) {
                $timelimit = ($timelimit * $Datas->pages) / $reference;
            }
        }
        //on libere de la ressource
        unset($Webservice);
        unset($Datas);
        //+20% de marge
        $timelimit += (20 * $timelimit) / 100;
        return $timelimit;
    }

    public function setData() {
        ini_set("memory_limit", "500M");
        if (!$this->error) {
            gc_enable();
            //Initialisation pagination
            $page = 1;
            //Une requete SQL pour inserer toutes les lignes d'un coup
            $sql = '';
            //Compteur du nombre de lignes inserees
            $countLine = 0;
            //Compteur de requetes effectuees
            $countRequest = 0;
            //Tableau des valeurs reelles pour la creation de la requete. Indispensable a l'objet PDO.
            $argumentsPDO = array();

            //while ($page > 0) { 
            while ($page > 0 && $page < 1500) {//145 - 165 - 185 - 250 - 185 - 165 - 185 - 210 - 250 - 400 - 600
                $u = $this->urls['data'] . http_build_query(array($this->primaryKey . '>' => 0, 'cny_max' => $this->limitPerRequest, 'cny_page' => $page, 'cny_sort' => $this->primaryKey));
                try {
                    $Webservice = new Webservice($u);
                    $Datas = $Webservice->getJSON();
                } catch (Exception $e) {
                    $this->error = $e->getMessage();
                    $page = 0;
                    break;
                }

                //on libere de la ressource
                unset($Webservice);

                //Controles elementaires
                if (!is_object($Datas) || !$Datas) {
                    $this->error = 'Pas de Datas';
                    return false;
                }
                if ($Datas->pages == 0) {
                    $page = 0;
                    break;
                }

                foreach ($Datas->{$this->table} as $Ligne) {
                    $tempValuesPDO = array();
                    foreach ($Ligne as $field => $value) {
                        if (in_array($field, $this->fields)) {
                            $tempValuesPDO[] = '?';
                            $argumentsPDO[] = $value;
                        }
                    }
                    $sql .= '
            (' . implode(',', $tempValuesPDO) . '),';

                    //on libere de la ressource
                    unset($tempValuesPDO);
                    $countLine++;
                }
                if (memory_get_usage() > 10000000) {
                    $sql = 'INSERT INTO `' . $this->table . '`
            (
                ' . implode(',
                ', $this->fields) . ')
            VALUES ' . substr($sql, 0, -1) . ';';
                    try {
                        $this->requests[] = $sql;
                        $countRequest++;
                        $s = $this->Database->Execute($sql, $argumentsPDO);
                        unset($s);
                    } catch (Exception $e) {
                        $this->error = $e->getMessage();
                        return false;
                    }
                    unset($sql);
                    unset($argumentsPDO);
                    $argumentsPDO = array();
                    $sql = '';
                }
                //Si on est arrive à la derniere page, on arrete le script
                if ($Datas->pages == $page) {
                    $page = 0;
                    break;
                } else {//sinon on va chercher la suivante
                    $page++;
                }
            }
            if (!$this->error) {
                $sql = 'INSERT INTO `' . $this->table . '`
            (
                ' . implode(',
                ', $this->fields) . ')
            VALUES ' . substr($sql, 0, -1) . ';';
                try {
                    $this->requests[] = $sql;
                    $this->Database->Execute($sql, $argumentsPDO);
                    $countRequest++;
                    $this->log = '
                            <br/>La table ' . $this->table . ' a été correctement importée avec ' . $countLine . ' lignes(s), par lot de ' . $this->limitPerRequest . ' ligne(s). 
                            <br/>Le script a consommé ' . Sys::convertBytes(memory_get_usage()) . ' de mémoire.
                            <br/>Le script a utilisé ' . $countRequest . ' requête(s).
                            <br/>' . Page::endTime();
                } catch (Exception $e) {
                    $this->error = $e->getMessage();
                }
            }
            gc_disable();
        }
    }

}

?>
